import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class MainSwing {

	public static final ImageIcon TELA_INICIAL = criaImagem("janela_semantica_normal.png");

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				final JFrame frame = new JFrame(
						"Analise Lexica, Sintatica e Semantica de PHP");
				// frame.setMinimumSize(new Dimension(800, 600));
				frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
				frame.setResizable(false);
				Container pane = frame.getContentPane();
				BoxLayout layout = new BoxLayout(pane, BoxLayout.Y_AXIS);

				pane.setLayout(layout);

				JButton button = new JButton(
						"Testar todos arquivos .php de uma pasta");
				button.setSize(300, 37);
				button.setLocation(50, 290);
				// button.setAlignmentX(Component.CENTER_ALIGNMENT);
				button.addActionListener(new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent arg0) {
						frame.setVisible(false);
						escolhaDePasta();
						frame.setVisible(true);
					}
				});

				JButton button2 = new JButton("Testar um arquivo .php");
				button2.setSize(300, 37);
				button2.setLocation(50, 340);
				// button2.setAlignmentX(Component.CENTER_ALIGNMENT);
				button2.addActionListener(new ActionListener() {

					@Override
					public void actionPerformed(ActionEvent arg0) {
						frame.setVisible(false);
						escolhaDeArquivo();
						frame.setVisible(true);
					}
				});
				JLabel label = new JLabel();
				label.setIcon(TELA_INICIAL);
				label.add(button);
				label.add(button2);
				// pane.add(button);
				// pane.add(button2);
				pane.add(label, BorderLayout.CENTER);

				frame.pack();
				frame.setVisible(true);
			}
		});
	}

	private static ImageIcon criaImagem(String imagem) {
		try {
			return new ImageIcon(ImageIO.read(new File(imagem)));
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public static JTextArea getTextArea(String msg) {
		JTextArea textarea = new JTextArea(msg);
		textarea.setFont(new Font("Monospaced", Font.PLAIN, 11));
		textarea.setOpaque(false);

		return textarea;
	}

	public static String trataExcecao(String message, String filePath) {
		String retorno = "";

		String[] linhas = message.split("\\*\\*");
		int linha = Integer.parseInt(linhas[0]);
		int coluna = Integer.parseInt(linhas[1]);

		if (linha <= 0) {
			retorno += "Erro em linha indeterminada.";
			retorno += System.lineSeparator();
			retorno += "Checar fim de arquivo inesperado (esperando fechamento de parenteses, chaves ou aspas)";
			return retorno;
		}

		String format = "%" + (coluna - 1) + "s^";

		try {
			Scanner sc = new Scanner(new File(filePath));
			for (int i = 0; i < linha - 1; i++) {
				sc.nextLine();
			}

			retorno += "Erro na linha " + linha + ".";
			retorno += System.lineSeparator();
			retorno += sc.nextLine();
			retorno += System.lineSeparator();
			retorno += String.format(format, " ");

		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Error e) {

		}

		return retorno;
	}

	public static void escolhaDePasta() {
		JFileChooser fileChooser = new JFileChooser(new File(".."));
		fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		fileChooser.setDialogTitle("Escolha uma pasta com os arquivos .php");
		
		int answer = fileChooser.showOpenDialog(null);
		if (answer == JFileChooser.APPROVE_OPTION) {
			testeDePasta(fileChooser.getSelectedFile().getAbsolutePath());
		} else {
			return;
		}
	}

	public static void escolhaDeArquivo() {
		boolean flag = false;

		while (!flag) {
			JFileChooser fileChooser = new JFileChooser(new File("."));
			fileChooser.setDialogTitle("Escolha um arquivo .php");
			
			int answer = fileChooser.showOpenDialog(null);
			if (answer == JFileChooser.APPROVE_OPTION) {
				if (fileChooser.getSelectedFile().getAbsolutePath()
						.endsWith(".php")) {
					testaArquivo(new File(fileChooser.getSelectedFile()
							.getAbsolutePath()));
					return;
				} else {
					JOptionPane.showMessageDialog(null,
							getTextArea("Arquivo deve ser um .php!"), "Erro!",
							JOptionPane.ERROR_MESSAGE);
				}
			} else {
				return;
			}
		}
	}

	public static void testeDePasta(String pasta) {
		File diretorio = new File(pasta);
		boolean temNaPasta = false;

		File[] children = diretorio.listFiles();
		if (children != null) {
			for (int i = 0; i < children.length; i++) {
				File file = children[i];
				if (file.getAbsolutePath().endsWith(".php")) {
					temNaPasta = true;
					testaArquivo(file);
				}
			}
		}

		if (!temNaPasta) {
			JOptionPane.showMessageDialog(null,
					getTextArea("Pasta nao possui nenhum arquivo .php!"),
					"Erro!", JOptionPane.ERROR_MESSAGE);
		}
	}

	public static void testaArquivo(File file) {
		String msg = "Resultados para o arquivo: " + file.getName();
		msg += System.lineSeparator();
		msg += System.lineSeparator();
		SemanticAnalyzer instance = SemanticAnalyzer.getInstance();
		instance.limpaTudo();
		try {
					
			PhpLexer lexer = new PhpLexer(new FileReader(file));
			lexer.setFileName(file.getName());
			PhpParser parser = new PhpParser(lexer);
			ParseNode rootNode = (ParseNode) parser.parse().value;
			
			
			if (!instance.validate()) {
				List<String> erros = instance.getErros();
				
				msg += "Erro Semantico";
				msg += System.lineSeparator();
				
				for(String s : erros) {
					if (s.contains("VariavelIndefinida:")) {
						String aux = s.replace("VariavelIndefinida:", "A variavel ");
						aux += " nao foi definida";
						msg += aux;
					} else {
						msg += s;
					}
					msg += System.lineSeparator();
				}
				
				JOptionPane.showMessageDialog(null, getTextArea(msg), "Resultado", JOptionPane.INFORMATION_MESSAGE);
			} else {
				JOptionPane.showMessageDialog(null, getTextArea(msg
					+ "Arquivo Valido!"), "Resultado", JOptionPane.INFORMATION_MESSAGE);	
			}
		} catch (Error e) {
			
			String mensagem = "Arquivo Invalido!";

			mensagem += System.lineSeparator();
			mensagem += System.lineSeparator();

			mensagem += "Erro Lexico/Sintatico";
			mensagem += System.lineSeparator();
			mensagem += System.lineSeparator();
			
			mensagem += trataExcecao(e.getMessage(), file.getAbsolutePath());

			JOptionPane.showMessageDialog(null, getTextArea(msg + mensagem),
					"Resultado", JOptionPane.INFORMATION_MESSAGE);

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
